<template>
  <div ref="reference" tabindex="0" @click="handleClick" @keydown.esc="handleEscape" @keydown.enter="handleEnter" @keydown.left="handleArrow($event, 'x', left)" @keydown.right="handleArrow($event, 'x', right)" @keydown.up="handleArrow($event, 'y', up)" @keydown.down="handleArrow($event, 'y', down)" @blur="blurColor" @focus="focusColor">
    <template v-for="(item, index) in list">
      <div :key="item + ':' + index" :class="[prefixCls + '-picker-colors-wrapper']">
        <div :data-color-id="index">
          <div :style="{background: item}" :class="[prefixCls + '-picker-colors-wrapper-color']"></div>
          <div :ref="'color-circle-' + index" :class="[prefixCls + '-picker-colors-wrapper-circle', hideClass]"></div>
        </div>
      </div>
      <!--<br v-if="lineBreak(list, index)">-->
    </template>
  </div>
</template>

<script>
import Emitter from '../../mixins/emitter';
import HandleEscapeMixin from './handleEscapeMixin';
import Prefixes from './prefixMixin';
import { clamp } from './utils';

export default {
  name: 'RecommendedColors',

  mixins: [Emitter, HandleEscapeMixin, Prefixes],

  props: {
    list: {
      type: Array,
      default: undefined
    }
  },

  data() {
    const columns = 12;
    const rows = Math.ceil(this.list.length / columns);
    const normalStep = 1;

    return {
      left: -normalStep,
      right: normalStep,
      up: -normalStep,
      down: normalStep,
      powerKey: 'shiftKey',
      grid: { x: 1, y: 1 },
      rows,
      columns
    };
  },

  computed: {
    hideClass() {
      return `${this.prefixCls}-hide`;
    },
    linearIndex() {
      return this.getLinearIndex(this.grid);
    },
    currentCircle() {
      return this.$refs[`color-circle-${this.linearIndex}`][0];
    }
  },

  methods: {
    getLinearIndex(grid) {
      return this.columns * (grid.y - 1) + grid.x - 1;
    },
    getMaxLimit(axis) {
      return axis === 'x' ? this.columns : this.rows;
    },
    handleArrow(e, axis, direction) {
      e.preventDefault();
      e.stopPropagation();

      this.blurColor();

      const grid = { ...this.grid };

      if (e[this.powerKey]) {
        if (direction < 0) {
          grid[axis] = 1;
        } else {
          grid[axis] = this.getMaxLimit(axis);
        }
      } else {
        grid[axis] += direction;
      }

      const index = this.getLinearIndex(grid);

      if (index >= 0 && index < this.list.length) {
        this.grid[axis] = clamp(grid[axis], 1, this.getMaxLimit(axis));
      }

      this.focusColor();
    },
    blurColor() {
      this.currentCircle.classList.add(this.hideClass);
    },
    focusColor() {
      this.currentCircle.classList.remove(this.hideClass);
    },
    handleEnter(e) {
      this.handleClick(e, this.currentCircle);
    },
    handleClick(e, circle) {
      e.preventDefault();
      e.stopPropagation();

      this.$refs.reference.focus();

      const target = circle || e.target;
      const colorId = target.dataset.colorId || target.parentElement.dataset.colorId;

      if (colorId) {
        this.blurColor();
        const id = Number(colorId) + 1;
        this.grid.x = id % this.columns || this.columns;
        this.grid.y = Math.ceil(id / this.columns);
        this.focusColor();
        this.$emit('picker-color', this.list[colorId]);
        this.$emit('change', { hex: this.list[colorId], source: 'hex' });
      }
    },
    lineBreak(list, index) {
      if (!index) {
        return false;
      }

      const nextIndex = index + 1;

      return nextIndex < list.length && nextIndex % this.columns === 0;
    }
  }
};
</script>
